package main

import (
	"06-GenericsTest/lists/arraylist"
	"06-GenericsTest/queues/arrayqueue"
	"errors"
	"fmt"
)

func min[T int | float64](a, b T) T {
	if a <= b {
		return a
	}
	return b
}

func function01() {
	x := min[int](10, 20)
	y := min[float64](0.1, -0.2)
	fmt.Println(x, y) // 10 -0.2

	fmin := min[float64] // 类型实例化
	z := fmin(1.1, 2.2)
	fmt.Println(z) // 1.1
}

type Value interface {
	int | float64
}

func max[T interface{ int | float64 }](a, b T) T {
	if a >= b {
		return a
	}
	return b
}

func max1[T Value](a, b T) T {
	if a >= b {
		return a
	}
	return b
}

// type Type[T int | float32] T
//type NewType [T * int][]T
//type NewType[T *int | *float32] []T

// type NewType[T *int,] []T
// type NewType[T interface{ *int }] []T
// type NewType[T interface{ *int | *float64 }] []T

func function02() {
	fmt.Println(max(1, 2), max1(2.1, -0.2))
}

type TypeStruct[T int | string] struct {
	Name string
	Data []T
}

func function03() {
	x := TypeStruct[int]{"Cauchy", []int{1, 2, 3}}
	fmt.Println(x) // {Cauchy [1 2 3]}

	/* 匿名结构体不支持泛型
	y := struct[T []int|[]string]{
		Name string
		Data T
	}[int]{
		"AQ",
		[]int{1, 2, 3},
	}
	*/
}

type Map[K int | string, V float32 | float64] map[K]V
type IValue interface {
	~string | ~int
}
type MyInt int

func sum[T IValue](a []T) (res T) {
	for _, e := range a {
		res += e
	}
	return
}

func function04() {
	m := Map[int, float64]{}
	m[1] = 1.0
	m[2] = 2.0
	fmt.Println(m) // map[1:1 2:2]

	a := []MyInt{1, 2, 3}
	fmt.Println(sum(a)) // 6
}

// 类型并集
type Int interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}
type Uint interface {
	~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}

// 类型交集
type A interface {
	Int
	Uint
	~string
}

// 错误，overlapping terms ~int and int
//type B interface {
//	int | ~int
//}

type B interface {
	int | interface{ ~int }
}

//type C[T int | string] interface {
//	~float64 | T
//}
//
//type D interface {
//	E
//}
//
//type E interface {
//	D
//}
//type F interface {
//	int | ~float64 | F
//}

type ReadWriter[T any] interface {
	Read(data T) (newData T)
	Writer(data T) error
}

//type G interface {
//	int | ReadWriter[int]
//}

type MyFloat[T ~float32 | ~float64] []T

func (mf MyFloat[T]) avg() T {
	var res T
	for _, e := range mf {
		res += e
	}
	return res / T(len(mf))
}

func function05() {
	var fa MyFloat[float32] = []float32{1.0, 2.1, 3.2}
	fmt.Println(fa.avg()) // 2.1000001
	f64 := MyFloat[float64]{1.0, 2.1, 3.2}
	fmt.Println(f64.avg()) // 2.1
}

//type MyStruct struct {}
// 错误：Method cannot have type parameters
//func (ms MyStruct) Add[T int | string](other T) MyStruct {}

type MyStruct[T int | string] struct {
	value T
}

func (ms MyStruct[T]) Add(other T) MyStruct[T] {
	ms.value += other
	return ms
}

func function06() {
	a := MyStruct[int]{1}
	b := MyStruct[string]{"1"}
	fmt.Println(a.Add(2), b.Add("34")) // {3} {134}
}

// 基本接口
type MyErr interface {
	Error() string
}

// 一般接口
type MyUint interface {
	~uint | ~uint8 | ~uint16
}

func function07() {
	var a MyErr = fmt.Errorf("这是基本接口")
	fmt.Println(a.Error()) // 这是基本接口
	// 错误：不能使用一般接口定义变量
	// var b MyUint
}

type Processer[T any] interface {
	Process(data T) T
	Save(data T) error
}

type XML struct{}

func (x XML) Process(data string) (newData string) {
	return ""
}
func (x XML) Save(data string) error {
	return errors.New("")
}

func function08() {
	var a Processer[string] = XML{}
	a.Process("")
	a.Save("")
}

type ProcesserNormal[T any] interface {
	int | ~struct{ value T }
	Process(data T) T
	Save(data T) error
}

type CSV struct {
	value string
}

func (c CSV) Process(data string) (newData string) {
	return ""
}
func (c CSV) Save(data string) error {
	return errors.New("")
}

func function09() {
	a := CSV{""}
	a.Process("")
	a.Save("")
}

// 测试链表
func function10() {
	l := arraylist.New[int](5, 2, 1, 4, 3)
	l.Sort(func(x, y int) int {
		return x - y
	})
	fmt.Println(l.String()) // ArrayList: [1, 2, 3, 4, 5]

	l.Remove(0)
	l.Add(0, 6)
	fmt.Println(l.String()) // ArrayList: [2, 3, 4, 5, 0, 6]
}

// 测试队列
func function11() {
	q := arrayqueue.New[int]()
	q.Enqueue(1)
	q.Enqueue(2)
	fmt.Println(q.String()) // ArrayQueue: [1, 2]
	q.Dequeue()
	q.Enqueue(3)
	fmt.Println(q.String()) // ArrayQueue: [2, 3]
	q.Clear()
	fmt.Println(q.Size()) // 0

	fq := arrayqueue.New[float64]()
	fq.Enqueue(10.1)
	fq.Enqueue(9.2)
	fq.Enqueue(8.3)
	fmt.Println(fq.String()) // ArrayQueue: [10.1, 9.2, 8.3]
}

func main() {
	//function01()
	//function02()
	//function03()
	//function04()
	//function05()
	//function06()
	//function07()
	//function08()
	//function09()
	//function10()
	//function11()
}
